import React, { useState } from 'react';
import {
  Paper,
  IconButton,
  Box,
  List,
  ListItem,
  ListItemButton,
  ListItemIcon,
  ListItemText,
  Typography,
  Divider,
} from '@mui/material';
import { getLayoutManagerInstance } from '@metacell/geppetto-meta-client/common/layout/LayoutManager';
import { WidgetStatus } from '@metacell/geppetto-meta-client/common/layout/model';
import { useAppSelector, useAppDispatch } from '../../redux/hooks';
import {
  EDIT_WIDGETS,
  DEFAULT_NETWORK_WIDGETS,
  TOP_PANEL,
  TOOLS_LIST,
  SIDEBAR_HEADINGS,
} from '../../constants';
import DrawerIcon from '../general/NetPyNEIcons';
import useStyles from './useStyles';
import Tooltip from '../general/Tooltip';
import {
  addWidget,
  activateWidget,
  updateWidget,
  newWidget,
} from '@metacell/geppetto-meta-client/common/actions';

const drawerOpenWidth = 'auto';
const drawerCloseWidth = 55;

interface DrawerItemProps {
  id: string;
  name: string;
  widget: any;
  expanded: boolean;
  createOrFocusWidget: (id: string) => void;
  disabled?: boolean;
  status: WidgetStatus;
  classes: any;
}

const DrawerItem: React.FC<DrawerItemProps> = ({
  id,
  name,
  widget,
  expanded,
  createOrFocusWidget,
  disabled = false,
  status,
  classes,
}) => (
  <Tooltip title={expanded ? '' : name} placement="right">
    <ListItemButton
      key={id}
      dense
      disableGutters
      disabled={disabled}
      className={widget ? classes.selected : classes.unselected}
      onClick={() => createOrFocusWidget(id)}
    >
      <ListItemIcon className={classes.icon}>
        <DrawerIcon
          name={id}
          selected={status !== WidgetStatus.MINIMIZED}
          disabled={status !== WidgetStatus.ACTIVE}
          highlight={status === WidgetStatus.ACTIVE}
        />
      </ListItemIcon>
      <ListItemText className={classes.text}>
        <Typography noWrap>{name}</Typography>
      </ListItemText>
    </ListItemButton>
  </Tooltip>
);

const Drawer: React.FC = () => {
  const [expand, setExpand] = useState(false);
  const dispatch = useAppDispatch();
  const { editMode, widgets } = useAppSelector((state: any) => ({
    editMode: state.general.editMode,
    widgets: state.widgets,
  }));

  const drawerClasses = useStyles({
    width: expand ? drawerOpenWidth : drawerCloseWidth,
    expand,
  });

  const layoutManager = getLayoutManagerInstance();

  const dispatchAction = (action: any) => {
    dispatch(action);
  };

  function createOrFocusWidget(widgetId: string): void {
    const widget = layoutManager.getWidget(widgetId);
    if (!widget) {
      const widgetConf = getNewWidgetConf(widgetId);
      if (widgetConf) {
        dispatchAction(newWidget({ path: widgetConf.id, ...widgetConf }));
      }
    } else {
      updateBorderWidget(widgetId);
    }
  }

  // Move python widget from BORDER to a visible tabset
  function updateBorderWidget(widgetId: string): void {
    const updatedWidget = { ...layoutManager.getWidget(widgetId) };
    updatedWidget.status = WidgetStatus.ACTIVE;
    updatedWidget.panelName = updatedWidget.defaultPanel || TOP_PANEL;
    dispatchAction(updateWidget(updatedWidget));
  }

  function getNewWidgetConf(widgetId: string): any {
    if (editMode) {
      // return a High Level Specification widget
      return EDIT_WIDGETS[widgetId] || null;
    }

    // return either 3dcanvas or python console
    return DEFAULT_NETWORK_WIDGETS[widgetId] || null;
  }

  function getMenu(): [any[], any[]] {
    const modelDrawerItems: any[] = [];
    const toolsDrawerItems: any[] = [];

    Object.values(widgets || {})
      .filter((widget: any) => {
        if (widget.specification !== TOOLS_LIST) {
          modelDrawerItems.push(widget);
        } else {
          toolsDrawerItems.push(widget);
        }
      });
    return [modelDrawerItems, toolsDrawerItems];
  }

  const mapItem = ({
    name,
    id,
  }: {
    name: string;
    id: string;
  }) => {
    const widget = widgets?.[id];
    const status = widget?.status || WidgetStatus.HIDDEN;

    return (
      <DrawerItem
        key={id}
        id={id}
        name={name}
        widget={widget}
        disabled={widget?.disabled}
        expanded={expand}
        classes={drawerClasses}
        createOrFocusWidget={createOrFocusWidget}
        status={status}
      />
    );
  };

  const paperClasses = `${expand ? drawerClasses.openDrawer : drawerClasses.closeDrawer}`;

  return (
    <Paper elevation={0} className={paperClasses}>
      <Box className={drawerClasses.container}>
        <Box px={1} py={2}>
          {expand && (
            <Box className="drawerListBox">
              <Typography
                variant="body2"
                sx={{
                  color: '#A8A5A5',
                  marginBottom: 2,
                  whiteSpace: 'nowrap',
                  fontSize: '0.875rem',
                }}
              >
                {editMode ? SIDEBAR_HEADINGS.MODEL : SIDEBAR_HEADINGS.PLOTS}
              </Typography>
            </Box>
          )}
          <List
            disablePadding
            sx={{
              '& .MuiListItem-gutters': {
                padding: '0.4rem 0',
              },
              '& .MuiListItemIcon-root': {
                minWidth: 32,
              },
              '& .MuiListItemText-root': {
                whiteSpace: 'nowrap',
              },
              '& .MuiSvgIcon-root': {
                color: '#EB517A',
              },
            }}
          >
            {getMenu()[0].map(mapItem)}
          </List>
          <Box
            className="drawerListBox"
            sx={{
              '& .MuiDivider-root': {
                marginTop: 2,
                marginBottom: 2.5,
              },
            }}
          >
            <Divider />
            {expand && (
              <Typography
                variant="body2"
                sx={{
                  color: '#A8A5A5',
                  marginBottom: 2,
                  whiteSpace: 'nowrap',
                  fontSize: '0.875rem',
                }}
              >
                {SIDEBAR_HEADINGS.TOOLS}
              </Typography>
            )}
          </Box>
          <List
            disablePadding
            sx={{
              '& .MuiListItem-gutters': {
                padding: '0.4rem 0',
              },
              '& .MuiListItemIcon-root': {
                minWidth: 32,
              },
              '& .MuiListItemText-root': {
                whiteSpace: 'nowrap',
              },
              '& .MuiSvgIcon-root': {
                color: '#EB517A',
              },
            }}
          >
            {getMenu()[1].map(mapItem)}
          </List>
        </Box>

        <Box
          sx={{
            textAlign: expand ? 'end' : 'center',
            padding: 0,
          }}
        >
          <Tooltip title={expand ? 'Collapse' : 'Expand'}>
            <IconButton
              className={drawerClasses.button}
              size="medium"
              onClick={() => {
                setExpand(!expand);
                setTimeout(() => window.dispatchEvent(new Event('resize')), 400);
              }}
            >
              {expand ? (
                <DrawerIcon name="arrow-left" fontSize="inherit" />
              ) : (
                <DrawerIcon name="arrow-right" fontSize="inherit" />
              )}
            </IconButton>
          </Tooltip>
        </Box>
      </Box>
    </Paper>
  );
};

export default Drawer;
